/*
 * G53_Basic_SPI_master_poll_example.c
 *
 * Created: 10/07/2014 20:37:55
 *  Author: jerome.semette
 */ 

#include "sam.h"
	
void System_clock_init (void);
void GPIO_init (void);
void SPI_master_init (void);
void SPI_Read_Write (uint8_t uiCS, uint16_t * pTxbuff , uint16_t * pRxbuff , uint32_t uiNbByte);


uint16_t TxBuff1[3] = {0x01,0x02,0x03};
uint16_t RxBuff1[3] = {0x0,0x0,0x0};

uint16_t TxBuff2[3] = {0x0101,0x0202,0x0303};
uint16_t RxBuff2[3] = {0x0,0x0,0x0};


void System_clock_init (void){
	/*Disable Watchdog*/
	WDT->WDT_MR = WDT_MR_WDDIS;
	/* Set Fast RC to 24 MHz */
	
	
}

void GPIO_init (void)
{
	/* Set PA11 in peripheral mode A - NPCS0 */
	PIOA->PIO_ABCDSR[0] &= ~(PIO_ABCDSR_P11) ;
	PIOA->PIO_ABCDSR[1] &= ~(PIO_ABCDSR_P11) ;
	PIOA->PIO_PER |= PIO_PER_P11;
	
	/* Set PA12 in peripheral mode A - MISO */
	PIOA->PIO_ABCDSR[0] &= ~(PIO_ABCDSR_P12) ;
	PIOA->PIO_ABCDSR[1] &= ~(PIO_ABCDSR_P12) ;
	PIOA->PIO_PER |= PIO_PER_P12;
	
	/* Set PA13 in peripheral mode A - MOSI */
	PIOA->PIO_ABCDSR[0] &= ~(PIO_ABCDSR_P13) ;
	PIOA->PIO_ABCDSR[1] &= ~(PIO_ABCDSR_P13) ;
	PIOA->PIO_PER |= PIO_PER_P13;
	
	/* Set PA14 in peripheral mode A - SPCK */
	PIOA->PIO_ABCDSR[0] &= ~(PIO_ABCDSR_P14) ;
	PIOA->PIO_ABCDSR[1] &= ~(PIO_ABCDSR_P14) ;
	PIOA->PIO_PER |= PIO_PER_P14;
	
	/* Set PA5 in peripheral mode B - NPCS1 */
	PIOA->PIO_ABCDSR[0] |= (PIO_ABCDSR_P5) ;
	PIOA->PIO_ABCDSR[1] &= ~(PIO_ABCDSR_P5) ;
	PIOA->PIO_PER |= PIO_PER_P5;
}

void SPI_master_init (void)
{
	//- Enable SPI Clock (SPI clock ID = SPI vector ID = 21)
	PMC->PMC_PCDR0 |= PMC_PCDR0_PID21 ;
	//- Disable SPI
	SPI->SPI_CR |= SPI_CR_SPIDIS;
	//- Reset SPI configuration
	SPI->SPI_CR |= SPI_CR_SWRST;
	//-  Set delay between Chip select change to 10 SPI clock period ((DLYBCS-1)/fspi)
	SPI->SPI_MR |= SPI_MR_DLYBCS(11);
	//- Set SPI as Master
	SPI->SPI_MR |= SPI_MR_MSTR;
	// Configure communication with slave 0 (CS0) */
	SPI->SPI_CSR[0] = ((0x01 << SPI_CSR_DLYBCT_Pos) | (0x01 << SPI_CSR_DLYBS_Pos) | (0x01 << SPI_CSR_SCBR_Pos) | SPI_CSR_CSNAAT | SPI_CSR_BITS_8_BIT | SPI_CSR_CPOL | SPI_CSR_NCPHA);
	// Configure communication with slave 1 (CS1) */
	SPI->SPI_CSR[1] = ((0x01 << SPI_CSR_DLYBCT_Pos) | (0x01 << SPI_CSR_DLYBS_Pos) | (0x02 << SPI_CSR_SCBR_Pos) | SPI_CSR_CSNAAT | SPI_CSR_BITS_16_BIT | SPI_CSR_CPOL);
	//- Enable SPI
	SPI->SPI_CR |= SPI_CR_SPIEN;
	SPI->SPI_CR &= ~(SPI_CR_SPIDIS);
}

void SPI_Read_Write (uint8_t uiCS, uint16_t * pTxbuff , uint16_t * pRxbuff , uint32_t uiNbByte)
{
	/* Init Tx and Rx counters*/
	uint32_t uiTxcnt = 0;
	uint32_t uiRxcnt = 0;
	
	SPI->SPI_MR |= (uiCS << SPI_MR_PCS_Pos);
	
	if (uiNbByte == 1)
	{
		/* Wait until TX register is empty */
		while(!(SPI->SPI_SR & SPI_SR_TDRE));
		/* Prepare Datum to send (start transfer) */
		SPI->SPI_TCR = pTxbuff[uiTxcnt];
		/* wait until datum is received (end of transfer)*/
		while(!(SPI->SPI_SR & SPI_SR_RXBUFF));
		/* Read received Datum  */
		pRxbuff[uiRxcnt] = SPI->SPI_RCR ;
	}
	
	if (uiNbByte > 1)
	{
		/* Prepare First Datum to send */
		while(!(SPI->SPI_SR & SPI_SR_TDRE));
		SPI->SPI_TCR = pTxbuff[uiTxcnt++];
		/* Prepare Second Datum to send */
		while(!(SPI->SPI_SR & SPI_SR_TDRE));
		SPI->SPI_TCR = pTxbuff[uiTxcnt++];
		
		while (uiTxcnt != (uiNbByte-1)){
			while(!(SPI->SPI_SR & SPI_SR_RXBUFF));
			pRxbuff[uiRxcnt++] = SPI->SPI_RCR ;		
			while(!(SPI->SPI_SR & SPI_SR_TDRE));
			SPI->SPI_TCR = pTxbuff[uiTxcnt++];
		}
		/* Read Previous to last datum */
		while(!(SPI->SPI_SR & SPI_SR_RXBUFF));
		pRxbuff[uiRxcnt++] = SPI->SPI_RCR ;
		/* Set last transfer */
		SPI->SPI_CR |= SPI_CR_LASTXFER;
		/* Read last datum */
		while(!(SPI->SPI_SR & SPI_SR_RXBUFF));
		pRxbuff[uiNbByte-1] = SPI->SPI_RCR ;
	}
	
}


/**
 * \brief Application entry point.
 *
 * \return Unused (ANSI-C compatibility).
 */
int main(void)
{
	/* Initialize the system an its clock */ 
    System_clock_init();
	/* Configure GPIOs */ 
	GPIO_init();
	/* Initialize SPI in master mode */
	SPI_master_init();
	
    while (1) 
    {
		/* Perform Transaction with first Slave (CS0) */
		SPI_Read_Write(0,TxBuff1,RxBuff1,3);
		/* Perform Transaction with Second Slave (CS1) */
		SPI_Read_Write(1,TxBuff2,RxBuff2,3);
    }
}
